
package com.yuheadline.media.service.impl;

import com.alibaba.nacos.common.utils.StringUtils;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dust.yuheadline.common.aliyun.oss.OssFileUploader;
import com.dust.yuheadline.common.aliyun.utils.AliOssProperties;
import com.dust.yuheadline.common.exception.CustomException;
import com.dust.yuheadline.common.utils.PageResult;
import com.dust.yuheadline.common.utils.ResponseCode;
import com.dust.yuheadline.common.utils.Result;
import com.yuheadline.media.mapper.MaterialMapper;
import com.yuheadline.media.service.MaterialService;
import com.yuheadline.media.util.ThreadLocalUtil;
import com.yuheadline.model.media.domain.MaterialImage;
import com.yuheadline.model.media.dto.MaterialPageQueryDto;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 素材表 Service 接口
 *
 * @author 高翔宇
 * @since 2024-05-2, 周四, 10:57
 */
@Service
@RequiredArgsConstructor
public class MaterialServiceImpl extends ServiceImpl<MaterialMapper, MaterialImage> implements MaterialService {
    private final MaterialMapper materialMapper;
    private final OssFileUploader ossFileUploader;
    private final AliOssProperties aliOssProperties;
    private final OSS oss;

    /**
     * 分页查询当前用户的素材
     */
    @Override
    public PageResult<List<MaterialImage>> pageList(@NonNull MaterialPageQueryDto materialPageQueryDto) {
        Long userId = ThreadLocalUtil.getUserId();
        if (userId == null) {
            throw new CustomException(ResponseCode.NOT_LOGIN);
        }
        int pageNum = materialPageQueryDto.getPageNum();
        int pageSize = materialPageQueryDto.getPageSize();
        Page<MaterialImage> materialPage = new Page<>(pageNum, pageSize);
        materialMapper.selectPage(materialPage, new LambdaQueryWrapper<MaterialImage>()
                .eq(MaterialImage::getUserId, userId)
                .orderByDesc(MaterialImage::getCreatedAt));
        return new PageResult<List<MaterialImage>>(materialPage.getTotal(), pageNum, pageSize).success(materialPage.getRecords().stream().peek(materialImage -> {
            // 如果素材URL为空，且对象名称不为空，则根据 objectName 生成URL，objectName 是上传到OSS的文件名
            if (!StringUtils.hasLength(materialImage.getUrl()) && StringUtils.hasLength(materialImage.getObjectName())) {
                materialImage.setUrl(oss.generatePresignedUrl(aliOssProperties.getBucketName(), materialImage.getObjectName(), new Date(System.currentTimeMillis() + 3600 * 1000)).toString());
            }
        }).toList());
    }

    /**
     * 上传素材
     */
    @Override
    public Result<?> upload(@NotNull MultipartFile file) {
        if (file.isEmpty()) {
            throw new CustomException(ResponseCode.FILE_EMPTY);
        }
        try {
            byte[] bytes = file.getBytes();
            String originalFilename = file.getOriginalFilename();
            String objectName;
            if (originalFilename != null) {
                objectName = UUID.randomUUID() + originalFilename.substring(file.getOriginalFilename().lastIndexOf("."));
            } else {
                objectName = UUID.randomUUID() + ".png";
            }
            String url = ossFileUploader.uploadAndGetPresignedUrl(bytes, objectName);
            Long userId = ThreadLocalUtil.getUserId();
            if (userId == null) {
                throw new CustomException(ResponseCode.NOT_LOGIN);
            }
            // 提取Endpoint的域名部分（去除可能存在的http/https协议前缀）
            String endpointDomain = aliOssProperties.getEndpoint()
                    .replaceFirst("^https?://", ""); // 正则表达式去除协议前缀

            // 拼接正确的永久URL（固定使用https协议保证安全）
            String bucketDomain = String.format("https://%s.%s",
                    aliOssProperties.getBucketName(),
                    endpointDomain);
            String permanentUrl =  bucketDomain + "/" + objectName;
            MaterialImage newMaterialImage = MaterialImage.builder()
                    .userId(userId)
                    .objectName(objectName)
                    .url(permanentUrl)
                    .createdAt(LocalDateTime.now())
                    .imageName(originalFilename != null ? originalFilename.substring(0, originalFilename.lastIndexOf(".")) : "")
                    .build();
            materialMapper.insert(newMaterialImage);
            return new Result<>().success("上传成功~", url);
        } catch (IOException e) {
            throw new CustomException(ResponseCode.UPLOAD_FAILED);
        }
    }

    /**
     * 根据id删除素材
     */
    @Override
    public Result<?> deleteById(@NotNull Long id) {
        Long userId = ThreadLocalUtil.getUserId();
        if (userId == null) {
            throw new CustomException(ResponseCode.NOT_LOGIN);
        }
        MaterialImage materialImage = materialMapper.selectById(id);
        if (materialImage == null) {
            throw new CustomException(ResponseCode.RESOURCE_NOT_FOUND);
        }
        if (!materialImage.getUserId().equals(userId)) {
            throw new CustomException(ResponseCode.FORBIDDEN);
        }
        materialMapper.deleteById(id);
        try {
            oss.deleteObject(aliOssProperties.getBucketName(), materialImage.getObjectName());
        } catch (OSSException | ClientException e) {
            log.warn("从 Aliyun OSS 删除原头像失败！");
        }
        return new Result<>().success("删除成功~");
    }
}